//
//  JFCTableView.swift
//  jianfeiApp2C
//
//  Created by Mac on 2020/4/20.
//  Copyright © 2020 com.yanjiuyuan. All rights reserved.
//

import UIKit
import CocoaLumberjack

// 回调方法里面不能用section 和 row来回调
public typealias DidSelectRowCallback = (_ viewModel: Any, _ sectionModel: JFCTableViewSection) -> ()
public typealias HeightCallback = (_ section: JFCTableViewSection) -> CGFloat
public typealias ViewCallback = (_ section: JFCTableViewSection) -> UIView?
public typealias ScrollCallback = (_ scrollView: UIScrollView) -> ()
public typealias CellCallback = (_ viewModel: JFCCellViewModelProtocol, _ cell: UITableViewCell) -> ()
public typealias DeleteCellCallback = (_ viewModel: Any, _ sectionModel: JFCTableViewSection) -> ()

public class JFCTableView: UITableView, UITableViewDelegate, UITableViewDataSource {
    
    private lazy var emptyVie = BaseEmptyView.init(frame: CGRect(x: 0, y: 0, width: CPScreenWidth, height: CPScreenHeight - CPNavBarHeight - 50 - CPTabHeight)).then { (view) in
        view.imgName = EMPTY_IMAGE
        view.isShowRefreshBtn = false
    }
    
    public var hidEmpty:Bool?
    public var heightForHeaderCallback: HeightCallback?
    public var viewForHeaderCallback: ViewCallback?
    public var heightForFooterCallback: HeightCallback?
    public var viewForFooterCallback: ViewCallback?
    public var scrollViewDidScroll: ScrollCallback?
    public var didSelectRowCallback: DidSelectRowCallback?
    public var deleteRowCallback: DeleteCellCallback?
    public var willBeginDragging: ScrollCallback?
    public var willDisplayCell: CellCallback?

    public var canEdit: Bool = false
    public var sections: [JFCTableViewSection] = [] {
        didSet {
            DispatchQueue.main.async {
                self.reloadData()
            }
        }
    }
    
    override init(frame: CGRect, style: UITableView.Style) {
        super.init(frame:frame, style: style)
        
        self.emptyVie.frame.size.height = self.frame.height
        self.separatorStyle = UITableViewCell.SeparatorStyle.none
        self.dataSource = self
        self.delegate = self
        
        self.estimatedRowHeight = 0.0
        self.estimatedSectionFooterHeight = 0.0
        self.estimatedSectionHeaderHeight = 0.0
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        self.dataSource = self
        self.delegate = self
        
        self.separatorStyle = UITableViewCell.SeparatorStyle.none
        self.estimatedRowHeight = 0.0
        self.estimatedSectionFooterHeight = 0.0
        self.estimatedSectionHeaderHeight = 0.0
    }
    
    
    /// MARK: UITableViewDataSource
    public func numberOfSections(in tableView: UITableView) -> Int {
        if self.hidEmpty ?? false {
            self.tableFooterView = UIView.init(frame: CGRect(x: 0, y: 0, width: 0.01, height: 0.01))
        }
        else {
            if sections.count == 0 {
                self.tableFooterView = self.emptyVie
            }
            else {
                self.tableFooterView = UIView.init(frame: CGRect(x: 0, y: 0, width: 0.01, height: 0.01))
            }
        }
        
        return sections.count
    }
    
    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        let sectionModel: JFCTableViewSection = self.sections[section]
        return sectionModel.viewModels.count
    }
    
    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard sections.count > indexPath.section else {
            DDLogError("JFCTableView fatal error: section nil")
            return UITableViewCell()
        }
        
        let section: JFCTableViewSection = self.sections[indexPath.section]
        guard section.viewModels.count > indexPath.row else {
            DDLogError("JFCTableView fatal error: viewModels nil")
            return UITableViewCell()
        }
        
        guard let vm = section.viewModels[indexPath.row] as? JFCCellViewModelProtocol else {
            return UITableViewCell()
        }
        
        vm.register(to: tableView)
        
        let cell: UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: vm.identifier)
        
        if cell is JFCCellProtocol {
            (cell as! JFCCellProtocol).configCell(viewModel: vm)
        }
        cell?.selectionStyle = UITableViewCell.SelectionStyle.none
        return cell ?? UITableViewCell()
    }
    
    public func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return self.canEdit
    }
    
    public func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        let section: JFCTableViewSection = self.sections[indexPath.section]
        guard let vm = section.viewModels[indexPath.row] as? JFCCellViewModelProtocol else {
            return
        }
        
        if editingStyle == .delete {
            if let callback = deleteRowCallback {
                callback(vm, section)
            }
        }
    }
    
    /// MARK: UITableViewDelegate
    /// section header 代理方法, 通过闭包的形式给外面调用
    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        let section: JFCTableViewSection = self.sections[indexPath.section]
        guard let vm = section.viewModels[indexPath.row] as? JFCCellViewModelProtocol else {
            return
        }
        
        if let callback = didSelectRowCallback {
            callback(vm, section)
        }
    }
    
    public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if indexPath.section < self.sections.count {
            let section: JFCTableViewSection = self.sections[indexPath.section]
            if indexPath.row < section.viewModels.count {
                if let vm = section.viewModels[indexPath.row] as? JFCCellViewModelProtocol {
                    return vm.cellHeight
                }
            }
        }
        
        return 44.0
    }
    
    public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        if section < self.sections.count {
            let sectionModel: JFCTableViewSection = self.sections[section]
            guard let callback = self.heightForHeaderCallback else {
                return 0.0
            }
            
            return callback(sectionModel)
        }
        
        return 0
    }
    
    public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        if section < self.sections.count {
            let sectionModel: JFCTableViewSection = self.sections[section]
            guard let callback = self.viewForHeaderCallback else {
                return nil;
            }
            
            return callback(sectionModel)
        }
        
        return UIView()
    }
    
    public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        if section < self.sections.count {
            let sectionModel: JFCTableViewSection = self.sections[section]
            guard let callback = self.heightForFooterCallback else {
                return 0.0
            }
            
            return callback(sectionModel)
        }
        
        return 0
    }
    
    public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        if section < self.sections.count {
            let sectionModel: JFCTableViewSection = self.sections[section]
            guard let callback = self.viewForFooterCallback else {
                return nil;
            }
            
            return callback(sectionModel)
        }
        
        return UIView()
    }
    
    public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        if let callback = willDisplayCell {
            if indexPath.section < self.sections.count {
                let section: JFCTableViewSection = self.sections[indexPath.section]
                if indexPath.row < section.viewModels.count {
                    if let vm = section.viewModels[indexPath.row] as? JFCCellViewModelProtocol {
                        callback(vm, cell)
                    }
                }
            }
        }
    }
    
    /// MARK: UIScrollViewDelegate
    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
        guard let callback = self.scrollViewDidScroll else {
            return
        }
        
        callback(scrollView)
    }
    
    public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        guard let callback = self.willBeginDragging else {
            return
        }
        
        callback(scrollView)
    }
}
